package com.atguigu.paymentdemo.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.paymentdemo.bo.OrderInfoBo;
import com.atguigu.paymentdemo.entity.CourseInfo;
import com.atguigu.paymentdemo.entity.OrderInfo;
import com.atguigu.paymentdemo.service.CourseInfoService;
import com.atguigu.paymentdemo.service.OrderInfoService;
import com.atguigu.paymentdemo.util.AjaxResult;
import com.atguigu.paymentdemo.vo.R;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.huifu.adapay.Adapay;
import com.huifu.adapay.core.AdapayCore;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.core.util.AdapaySign;
import com.huifu.adapay.model.MerConfig;
import com.huifu.adapay.model.Payment;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

@CrossOrigin//开放前端的跨域访问
@Api(tags = "订单信息")
@RestController
@RequestMapping("orderInfo")
@RequiredArgsConstructor
@Slf4j
public class OrderInfoController {

    @Value("${adapay.apiKey}")
    private String apiKey;
    @Value("${adapay.mockApiKey}")
    private String mockApiKey;
    @Value("${adapay.rsaPrivateKey}")
    private String rsaPrivateKey;
    @Value("${adapay.appId}")
    private String appId;
    @Value("${adapay.notifyUrl}")
    private String notifyUrl;
    private final OrderInfoService orderInfoService;
    private final CourseInfoService courseInfoService;


    @ApiOperation("根据userId获取订单信息")
    @GetMapping("/getMyOrderInfo")
    public R getMyOrderInfo(Integer userId) {
        QueryWrapper<OrderInfo> qw = new QueryWrapper<OrderInfo>();
        qw.eq("user_id", userId);
        List<OrderInfo> orderInfo = orderInfoService.list(qw);
        for (OrderInfo o : orderInfo){
            CourseInfo course = courseInfoService.getById(o.getProductId());
            o.setCourseInfo(course);
        }
        return R.ok().data("data", orderInfo);
    }

    /**
     * 不分页查询
     *
     * @param bo 课程
     * @return /
     */
    @ApiOperation(value = "判断用户订单是否已购买-返回boolean在data中")
    @PostMapping(value = "/getOrderInfo", produces = {"application/json;charset=UTF-8"})
    public AjaxResult getOrderInfo(@RequestBody @Validated OrderInfoBo bo) {

        QueryWrapper<OrderInfo> qw = new QueryWrapper<OrderInfo>();
        qw.eq("user_id", bo.getUserId());
        qw.eq("product_id", bo.getInfoId());
        qw.eq("order_status", '1');
        OrderInfo info = orderInfoService.getOne(qw);
        boolean flag = false;
        if (info != null && info.getId() != null) {
            flag = true;
        }
        return AjaxResult.success(flag);
    }

    @ApiOperation(value = "添加订单")
    @PostMapping(value = "/addOrder", produces = {"application/json;charset=UTF-8"})
    public AjaxResult addOrder(@RequestBody @Validated OrderInfoBo bo) {
        CourseInfo courseInfo = courseInfoService.getById(bo.getInfoId());
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setTitle(courseInfo.getCourseName());
        orderInfo.setOrderStatus("0");
        orderInfo.setOrderNo(System.currentTimeMillis()+"");
        orderInfo.setUserId(bo.getUserId());
        orderInfo.setProductId(bo.getInfoId());
        orderInfo.setTotalFee(courseInfo.getRealPrice());
        orderInfo.setCreateTime(new Date());
        orderInfoService.save(orderInfo);
        return AjaxResult.success(orderInfo.getId());
    }


        @ApiOperation("统一支付")
    @PostMapping("/unifiedOrder")
    public AjaxResult executePayment(HttpServletRequest request, @RequestBody OrderInfo orderInfo) throws Exception {
        /**
         * debug 模式，开启后有详细的日志
         */
        Adapay.debug = true;

        /**
         * prodMode 模式，默认为生产模式，false可以使用mock模式
         */
        Adapay.prodMode = true;

        /**
         * 初始化商户配置，服务器启动前，必须通过该方式初始化商户配置完成
         * apiKey为prod模式的API KEY
         * mockApiKey为mock模式的API KEY
         * rsaPrivateKey为商户发起请求时，用于请求参数加签所需要的RSA私钥
         */
        MerConfig merConfig = new MerConfig();
        merConfig.setApiKey(apiKey);
        merConfig.setApiMockKey(mockApiKey);
        merConfig.setRSAPrivateKey(rsaPrivateKey);
        Adapay.initWithMerConfig(merConfig);
        System.out.println("=======execute payment begin=======");

        OrderInfo info = orderInfoService.getById(orderInfo.getId());
        if(info == null) {
            throw new RuntimeException("订单信息不存在");
        }
        if("1".equals(info.getOrderStatus())) {
            throw new RuntimeException("只有未支付的详单能发起支付");
        }
        //创建支付对象的参数，全部参数请参考 https://docs.adapay.tech/api/index.html
        Map<String, Object> paymentParams = new HashMap<>(10);
        paymentParams.put("app_id", appId);
        paymentParams.put("order_no", info.getOrderNo());
        paymentParams.put("pay_channel", "wx_pub");
        paymentParams.put("pay_amt", info.getTotalFee());

        paymentParams.put("goods_title", info.getTitle());
        paymentParams.put("goods_desc", info.getTitle());


        paymentParams.put("div_members", "");

        Map<String, Object> deviceInfo = new HashMap<>(2);

        deviceInfo.put("device_ip", "127.0.0.1");
        deviceInfo.put("device_mac", "");
        deviceInfo.put("device_type", "1");
        deviceInfo.put("device_imei", "");
        deviceInfo.put("device_imsi", "");
        deviceInfo.put("device_iccId", "ICCID");
        deviceInfo.put("device_wifi_mac", "WIFIMAC");

        paymentParams.put("device_info", deviceInfo);

        Map<String, Object> expendParams = new HashMap<>(2);
        String openId = "oePKp5jZ1kUSFeXICte9A5CnkazY";//微信授权获取
        Cookie[] cookies = request.getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
                if("openid".equals(cookie.getName())) {
                    openId = cookie.getValue();
                }
            }
        }
        log.info("openId===="+openId);
        expendParams.put("open_id", openId);
        expendParams.put("is_raw", "1");
        expendParams.put("callback_url", notifyUrl);
        expendParams.put("limit_pay", "1");

        paymentParams.put("expend", expendParams);
        paymentParams.put("notify_url", notifyUrl);

        //调用sdk方法，创建支付，得到支付对象
        Map<String, Object> payment = new HashMap<>();
        try {

            payment = Payment.create(paymentParams);
        } catch (BaseAdaPayException e) {
            e.printStackTrace();
        }

        String error_code = (String) payment.get("error_code");
        if (null != error_code) {
            log.info("创建支付返回参数：" + JSON.toJSONString(payment));

            String error_msg = (String) payment.get("error_msg");
            log.info("error_code:" + error_code + "............." + error_msg);
        }

        return AjaxResult.success(payment);
    }


    @PostMapping("/callback")
    public void callback(HttpServletRequest request) {
        try {
            //验签请参data
            String data = request.getParameter("data");
            //验签请参sign
            String sign = request.getParameter("sign");
            //验签标记
            boolean checkSign;
            //验签请参publicKey
            String publicKey = AdapayCore.PUBLIC_KEY;
            log.info("验签请参：data={}sign={}");
            //验签
            checkSign = AdapaySign.verifySign(data, sign, publicKey);
            if(checkSign){
                //验签成功逻辑
                log.info("成功返回数据data:"+data);
                JSONObject obj = JSONObject.parseObject(data);
                String order_no = obj.getString("order_no");
                log.info("order_no::"+order_no);
                String amount = obj.getString("pay_amt");
                OrderInfo orderInfo = orderInfoService.getOne(Wrappers.<OrderInfo>lambdaQuery()
                        .eq(OrderInfo::getOrderNo,order_no));
                log.info("orderInfo：："+orderInfo);
                if(orderInfo != null) {
                    //if (Objects.equals(orderInfo.getTotalFee(),amount)) {
                        orderInfo.setOrderStatus("1");
                        orderInfoService.updateById(orderInfo);
                        // 修改购买次数
                        CourseInfo course = courseInfoService.getById(orderInfo.getProductId());
                        CourseInfo courseInfo = new CourseInfo();
                        courseInfo.setId(orderInfo.getProductId());
                        courseInfo.setPayCount(course.getPayCount()+1);
                        courseInfoService.updateById(courseInfo);
//                    } else {
//                        throw new RuntimeException("付款金额与订单金额不等");
//                    }
                }else{
                    throw new RuntimeException("订单不存在");
                }
            }else {
                //验签失败逻辑
                throw new RuntimeException("回调验签失败");
            }
        }catch (Exception e){
            log.info("异步回调开始，参数，request={}",e);
        }
        return ;
    }

    public static void main(String[] args) {
        String str = "{\"app_id\":\"app_4cabfad7-030c-4c9e-99bc-b4aa7bd1cce5\",\"created_time\":\"20230201175129\",\"description\":\"\",\"end_time\":\"20230201175134\",\"expend\":{\"bank_type\":\"OTHERS\",\"open_id\":\"o8jhot8lEuRLoBMeqpVSSUPAqmh8\",\"sub_open_id\":\"oePKp5oI9rQ37-mnCPFQJjtix26w\"},\"fee_amt\":\"0.00\",\"id\":\"002112023020117512810466795890087981056\",\"order_no\":\"1675245088566\",\"out_trans_id\":\"4200001768202302016789495277\",\"party_order_id\":\"02212302016428896105828\",\"pay_amt\":\"0.01\",\"pay_channel\":\"wx_pub\",\"status\":\"succeeded\",\"wx_user_id\":\"\"}";
        JSONObject obj = JSONObject.parseObject(str);
        String order_no = obj.getString("order_no");
        String status = obj.getString("status");
        System.out.println(order_no);
        System.out.println(status);

    }
}
